#include <QIcon>
#include <QAction>
#include <QComboBox>
#include <QFontComboBox>
#include <QColorDialog>
#include <QTextList>
#include <QTextBlock>
#include <QTextCursor>
#include <QColor>
#include <QFileDialog>
#include <QTextDocumentFragment>
#include <QMessageBox>
#include <QRegExp>
#include "constants.h"
#include "formattededitor.h"
#include "tablesizewidget.h"
#include "Change/textchange.h"
#include "Change/formatchange.h"
#include "Change/tablechange.h"
#include "Change/imagechange.h"
#include "Preferences/preferences.h"
#include "Networking/documentmanager.h"
#include "WelcomeScreen/welcomescreen.h"

const int FormattedEditor::TOOLBAR_HEIGHT = 40;

FormattedEditor::FormattedEditor(DocumentManager *newManager) : Editor(newManager)
{
	toolBar = new FormattingToolBar(this);

	setViewportMargins(0, TOOLBAR_HEIGHT, 0, 0);

	//set the default font based on the preferences dialog
	QFont newDefaultFont;

	if (!Preferences::getInstance()->getValue(Preferences::SETTING_USE_SYSTEM_FORMATTED_FONT).toBool())
	{
		newDefaultFont = Preferences::getInstance()->getValue(Preferences::SETTING_DEFAULT_FORMATTED_FONT).value<QFont>();
		newDefaultFont.setPointSize(Preferences::getInstance()->getValue(Preferences::SETTING_DEFAULT_FORMATTED_FONT_SIZE).toInt());
	}
	else
	{
		newDefaultFont = QFont("SansSerif");
		newDefaultFont.setPointSize(DEFAULT_FONT_SIZE);
	}

	document()->setDefaultFont(newDefaultFont);
	setCurrentFont(newDefaultFont);

	//connect signals and slots
	connect(document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(textChanged(int,int,int)));
	connect(document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(checkForTabOnList(int,int,int)));
}

void FormattedEditor::resizeEvent(QResizeEvent *event)
{
	toolBar->setGeometry(QRect(contentsRect().left(), contentsRect().top(), width(), TOOLBAR_HEIGHT));

	QTextEdit::resizeEvent(event);
}

/**
  * Function detects if a file is a formatted file. We should use perhaps
  * a header (like doctype for HTML) or metadata to detect this.
  */
bool FormattedEditor::isFormattedFile(const QString fileName)
{
	return fileName.endsWith(FORMATTED_FILE_EXT);
}

void FormattedEditor::saveFile()
{
	file.open(QIODevice::WriteOnly);
	file.write(toHtml().toLatin1());

	WelcomeScreen::getInstance()->addRecentFile(file.fileName(), FORMATTED);
}

/**
  *	Delivers a new change from the server (via the session and document manager)
  */
void FormattedEditor::receiveChange(QByteArray change)
{
	Message::opType op = Message::getOpType(change);

	if (op == Message::ADD_TEXT)
	{
		handleAddTextChange(change);
	}
	else if (op == Message::ADD_HTML)
	{
		handleHtmlTextChange(change);
	}
	else if (op == Message::REMOVE)
	{
		handleRemoveTextChange(change);
	}
	else if (op == Message::CHANGE_FORMAT)
	{
		handleFormatChange(change);
	}
	else if (op == Message::ADD_TABLE)
	{
		handleAddTableChange(change);
	}
	else if (op == Message::ADD_IMAGE)
	{
		handleAddImageChange(change);
	}
}

void FormattedEditor::handleAddTextChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	TextChange txtChg(change);

	if (txtChg.getUserId() != documentManager->getLocalUserId())
	{
		QTextCursor cursor(document());

		int pos = txtChg.getPosition();

		//ensure that the end position is within the document
		if (pos >= document()->characterCount())
			pos = document()->characterCount() - 1;

		cursor.setPosition(pos);

		//set user highlighting format
		QTextCharFormat userNumberFormat;
		userNumberFormat.setProperty(QTextFormat::UserProperty, QVariant(txtChg.getUserId() + 1));
		cursor.mergeCharFormat(userNumberFormat);

		cursor.insertText(txtChg.getData());

		checkForTabOnList(0,0,txtChg.getNum());	//check tabs in case this is a list

		highlighter->rehighlight();	//manually rehighlight the contents

		qDebug("count_after_rec:%d",document()->characterCount());
	}

	changeList.push_back((Change)txtChg);

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::handleHtmlTextChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	TextChange txtChg(change);

	if (txtChg.getUserId() != documentManager->getLocalUserId())
	{
		QTextCursor cursor(document());
		cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, txtChg.getPosition());

		cursor.insertHtml(txtChg.getData());

		//fix up highlighting
		cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, cursor.position() - txtChg.getPosition());
		QTextCharFormat userNumberFormat;
		userNumberFormat.setProperty(QTextFormat::UserProperty, QVariant(txtChg.getUserId() + 1));
		cursor.mergeCharFormat(userNumberFormat);

		highlighter->rehighlight();	//manually rehighlight the contents
	}

	changeList.push_back((Change)txtChg);

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::handleRemoveTextChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	TextChange txtChg(change);

	if (txtChg.getUserId() != documentManager->getLocalUserId())
	{
		QTextCursor cursor(document());
		cursor.setPosition(txtChg.getPosition());
		cursor.setPosition(txtChg.getPosition() + txtChg.getNum(), QTextCursor::KeepAnchor);
		cursor.removeSelectedText();
	}

	changeList.push_back((Change)txtChg);

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::handleFormatChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	FormatChange formatChg(change);

	if (formatChg.getUserId() != documentManager->getLocalUserId())
	{
		//get the selection
		QTextCursor cursor(document());
		cursor.setPosition(formatChg.getPosition());
		cursor.setPosition(formatChg.getPosition() + formatChg.getNum(), QTextCursor::KeepAnchor);

		//fix up alignment
		if (formatChg.getAlignChanged())
		{
			QTextBlockFormat blockFormat;
			blockFormat.setAlignment(formatChg.getAlign());
			cursor.mergeBlockFormat(blockFormat);
		}

		//fix up bullet/numbered points
		if (formatChg.getListChanged())
			handleListChange(cursor, formatChg.getList());

		//create a textchar format with all properties and merge
		QTextCharFormat newFormat;

		if (formatChg.getBoldChanged())
			newFormat.setFontWeight(formatChg.getBold());

		if (formatChg.getItalicsChanged())
			newFormat.setFontItalic(formatChg.getItalics());

		if (formatChg.getUnderlineChanged())
			newFormat.setFontUnderline(formatChg.getUnderline());

		if (formatChg.getFontSizeChanged())
			newFormat.setFontPointSize((qreal)formatChg.getFontSize());

		if (formatChg.getFontFamilyChanged())
			newFormat.setFontFamily(formatChg.getFontFamily());

		if (formatChg.getForeColourChanged())
		{
			QBrush brush = newFormat.foreground();
			brush.setColor(QColor(formatChg.getForeColour()));
			brush.setStyle(Qt::SolidPattern);
			newFormat.setForeground(brush);
		}

		if (formatChg.getBackColourChanged())
		{
			QBrush brush = newFormat.background();
			brush.setColor(QColor(formatChg.getBackColour()));
			brush.setStyle(Qt::SolidPattern);
			newFormat.setBackground(brush);
		}

		cursor.mergeCharFormat(newFormat);
	}

	changeList.push_back((Change)formatChg);

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::handleAddTableChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	TableChange tableChg(change);

	if (tableChg.getUserId() != documentManager->getLocalUserId())
	{
		QTextCursor cursor(document());
		cursor.setPosition(tableChg.getPosition());
		cursor.insertTable(tableChg.getRows(), tableChg.getCols());
	}

	changeList.push_back((Change)tableChg);

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::handleAddImageChange(QByteArray change)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	ImageChange imgChg(change);

	if (imgChg.getUserId() != documentManager->getLocalUserId())
	{
		QTextCursor cursor(document());
		cursor.setPosition(imgChg.getPosition());

		QImage img;

		if (!img.loadFromData(imgChg.getImageData()))
		{
			QMessageBox err(QMessageBox::Critical, "Error!", "Could not load image!");
			err.exec();
		}
		else
		{
			document()->blockSignals(true);
			textCursor().insertImage(img);
			document()->blockSignals(false);
		}
	}

	changeList.push_back((Change)imgChg);

	document()->blockSignals(previousSignalState);
}


/**
  * A public slot, which handles textual changes to the document - turning them into
  * text and/or formatting messages. Note that paste and object(lists,images,tables) operations
  * are NOT handled here (except for simple deletions where they are treated as chars).
  *
  * (The above implies that ONLY single character additions are processed here)
  */
void FormattedEditor::textChanged(int position, int charsRemoved, int charsAdded)
{
	//get the character/s
	QTextCursor cursor = textCursor();
	cursor.setPosition(position);

	int posEnd = position + charsAdded;

	//ensure that the end position is within the document
	if (posEnd >= document()->characterCount())
		posEnd = document()->characterCount() - 1;

	cursor.setPosition(posEnd, QTextCursor::KeepAnchor);

	QString data = cursor.selectedText();

	//special case for lists
	if (cursor.currentList() != 0)
	{
		if (charsAdded > 1)
		{
			TextChange addChange(Change::ADD_TEXT, revisionNum++, documentManager->getLocalUserId(), docId, position+charsAdded, 1, "\n");
			documentManager->sendChange(addChange.toBytes());
			return;
		}
	}

	//another special case for list... ugh!
	for (int i = 0; i < data.length(); i++)
	{
		if (charsAdded > 1 && (data.at(i).unicode() == 8233 || data.at(i).unicode() == 8232))
		{
			document()->blockSignals(true);
			textCursor().deletePreviousChar();
			textCursor().insertText("\n");
			document()->blockSignals(false);

			toggleList(false, 0);

			return;
		}
	}

	if (charsRemoved)
	{
		TextChange remChange(Change::REMOVE, revisionNum++, documentManager->getLocalUserId(), docId, position, charsRemoved, NULL);
		documentManager->sendChange(remChange.toBytes());
	}

	if (charsAdded)
	{
		TextChange addChange(Change::ADD_TEXT, revisionNum++, documentManager->getLocalUserId(), docId, position, charsAdded, data);
		documentManager->sendChange(addChange.toBytes());

		//fix up local highlighting
		document()->blockSignals(true);
		QTextCharFormat userNumberFormat;
		userNumberFormat.setProperty(QTextFormat::UserProperty, QVariant(documentManager->getLocalUserId() + 1));
		cursor.mergeCharFormat(userNumberFormat);
		document()->blockSignals(false);

		//dont look for formatting info if we removed characters - this means user had a selection and could not
		// have changed the formatting data
		if (charsRemoved)
			return;

		//automatically send info if at beginning of document
		if (position == 0)
		{
			QTextCharFormat format = cursor.charFormat();

			//set the fontSize and fontFamily to defaults if they are not set
			if (format.fontFamily().isEmpty() || format.fontPointSize() == 0)
			{
				QFont newDefaultFont = document()->defaultFont();	//that's right, I need to set the font to defaultFont MANUALLY.
				setCurrentFont(newDefaultFont);
				format.setFont(newDefaultFont);
			}

			FormatChange formatChg(revisionNum++, documentManager->getLocalUserId(), docId, position, charsAdded);

			formatChg.setBold(format.fontWeight());
			formatChg.setItalics(format.fontItalic());
			formatChg.setUnderline(format.fontUnderline());
			formatChg.setFontSize((int)format.fontPointSize());
			formatChg.setFontFamily(format.fontFamily());
			formatChg.setForeColour(format.foreground().color().rgb());

			//only send background data IF a background is defined
			if (cursor.charFormat().background().style() != Qt::NoBrush)
				formatChg.setBackColour(format.background().color().rgb());

			documentManager->sendChange(formatChg.toBytes());
		}

		QTextCursor currCursor = textCursor();
		QTextCursor prevCursor = textCursor();
		prevCursor.movePosition(QTextCursor::PreviousCharacter);

		//don't look for new formatting info if we are at the start of a new line and have not written anything
		//(exception - if the previous line was blank - due to qt being a bit annoying)
		if (currCursor.atBlockStart() && (prevCursor.block().length() > 1))
			return;

		//Since Qt gets the NEXT charFormat instead of the PREVIOUS one - BUT ONLY IF
		//we are at the start of a block - we need to go an extra character backwards
		//if the previous cursor is at the beginning of the same block
		if (prevCursor.atBlockStart() && (prevCursor.block().blockNumber() == currCursor.block().blockNumber()))
		{
			prevCursor.movePosition(QTextCursor::PreviousCharacter);
		}

		//check for formatting changes
		QTextCharFormat prevFmt = prevCursor.charFormat();
		QTextCharFormat currFmt = currCursor.charFormat();

		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, position, charsAdded);

		if (currFmt.fontWeight() != prevFmt.fontWeight())
			fc.setBold(currFmt.fontWeight());

		if (currFmt.fontItalic() != prevFmt.fontItalic())
			fc.setItalics(currFmt.fontItalic());

		if (currFmt.fontUnderline() != prevFmt.fontUnderline())
			fc.setUnderline(currFmt.fontUnderline());

		if (currFmt.fontPointSize() != prevFmt.fontPointSize())
			fc.setFontSize(currFmt.fontPointSize());

		if (currFmt.fontFamily() != prevFmt.fontFamily())
			fc.setFontFamily(currFmt.fontFamily());

		if ((currFmt.foreground().color() != prevFmt.foreground().color()) && currFmt.foreground().style() != Qt::NoBrush)
			fc.setForeColour(currFmt.foreground().color().rgb());

		if ((currFmt.background().color() != prevFmt.background().color()) && currFmt.background().style() != Qt::NoBrush)
			fc.setBackColour(currFmt.background().color().rgb());

		if (!fc.isEmpty())
			documentManager->sendChange(fc.toBytes());
	}
}

/**
  * A Public Slot:
  * Checks if the changed character is a TAB (\t) if it is, then we need to handle making an
  * indented sub list, if the user has their cursor positioned on a list
  */
void FormattedEditor::checkForTabOnList(int position, int charsRemoved, int charsAdded)
{
	position = 0;
	charsRemoved = 0;

    if (charsAdded == 1)
    {
		QTextCursor cursor = textCursor();
		cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor);

		if (cursor.selectedText() == "\t" && cursor.currentList() != 0 && cursor.atBlockStart())
		{
			int oldStyle = cursor.currentList()->format().style();
			int newStyle;

			if (oldStyle >= -3)
			{
				//the list is bullet points (valid styles are -1,-2,-3)
				newStyle = (oldStyle % -3) - 1;
			}
			else
			{
				//the list is numbered (valid styles are -4,-5,-6,-7,-8)
				newStyle = ((oldStyle + 3) % -5) - 4;
			}

			bool previousBlockState = document()->signalsBlocked();
			document()->blockSignals(true);

			cursor.removeSelectedText();
			cursor.currentList()->remove(cursor.block());
			cursor.createList((QTextListFormat::Style)newStyle);

			document()->blockSignals(previousBlockState);
		}
    }
}

void FormattedEditor::insertFromMimeData(const QMimeData *source)
{
	if (source->hasHtml())
	{
		textCursor().removeSelectedText();

		int startPos = textCursor().position();

		TextChange addChange(Change::ADD_HTML, revisionNum++, documentManager->getLocalUserId(), docId,
							 startPos, source->html().length(), source->html());
		documentManager->sendChange(addChange.toBytes());

		document()->blockSignals(true);

		//remove any images (time constraints do not allow implementation of these...NOOOOOOO!!!!)
		QString html = source->html();
		QRegExp imgRegex("<img*src=\"*\"*/>");
		imgRegex.setPatternSyntax(QRegExp::Wildcard);
		html.remove(imgRegex);

		textCursor().insertHtml(html);

		//fix up local highlighting
		QTextCursor startCursor = textCursor();
		startCursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, textCursor().position() - startPos);
		QTextCharFormat userNumberFormat;
		userNumberFormat.setProperty(QTextFormat::UserProperty, QVariant(documentManager->getLocalUserId() + 1));
		startCursor.mergeCharFormat(userNumberFormat);

		highlighter->rehighlight();

		document()->blockSignals(false);
	}
}


void FormattedEditor::setFontWeight(int weight)
{
	document()->blockSignals(true);
	QTextEdit::setFontWeight(weight);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setBold(weight);
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setFontItalic(bool italic)
{
	document()->blockSignals(true);
	QTextEdit::setFontItalic(italic);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setItalics(italic);
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setFontUnderline(bool underline)
{
	document()->blockSignals(true);
	QTextEdit::setFontUnderline(underline);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setUnderline(underline);
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setFontPointSize(qreal s)
{
	document()->blockSignals(true);
	QTextEdit::setFontPointSize(s);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setFontSize((int)s);
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setCurrentFont(const QFont &f)
{
	document()->blockSignals(true);
	QTextEdit::setCurrentFont(f);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setFontFamily(f.family());
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setTextColor(const QColor & c)
{
	document()->blockSignals(true);
	QTextEdit::setTextColor(c);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setForeColour(c.rgb());
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setTextBackgroundColor(const QColor & c)
{
	document()->blockSignals(true);
	QTextEdit::setTextBackgroundColor(c);
	document()->blockSignals(false);

	if (textCursor().hasSelection())
	{
		FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
						(textCursor().selectionEnd() - textCursor().selectionStart()));
		fc.setBackColour(c.rgb());
		documentManager->sendChange(fc.toBytes());
	}
}

void FormattedEditor::setAlignment(Qt::Alignment a)
{
	document()->blockSignals(true);
	QTextEdit::setAlignment(a);
	document()->blockSignals(false);

	//alignment is to be sent with OR without a selection
	FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
					(textCursor().selectionEnd() - textCursor().selectionStart()));
	fc.setAlign(a);
	documentManager->sendChange(fc.toBytes());
}

void FormattedEditor::toggleList(bool listOn, int style)
{
	if (!listOn)
		style = 0;	//if the list is to be turned off

	//send the change to everyone
	FormatChange fc(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().selectionStart(),
					(textCursor().selectionEnd() - textCursor().selectionStart()));
	fc.setList(style);
	documentManager->sendChange(fc.toBytes());

	//fix the list up in the document
	handleListChange(textCursor(), style);
}

/**
  * Will either create or destroy a list at the current position, based on \a listOn
  * The style of the list is given by \a style (send either bullet or numbered style)
  */
void FormattedEditor::handleListChange(QTextCursor cursor, int style)
{
	bool previousSignalState = document()->signalsBlocked();
	document()->blockSignals(true);

	if (style < 0)
	{
		cursor.createList((QTextListFormat::Style)style);
	}
	else
	{
		//find the current list in the document
		QTextList *currentList = cursor.currentList();

		if (currentList != 0)
		{
			int listIndent = currentList->format().indent();

			//take the block out of the list
			currentList->remove(cursor.block());

			//fix the indenting (surely there is an easier way to do this)
			QTextBlockFormat blockFormat = cursor.block().blockFormat();
			blockFormat.setIndent(blockFormat.indent() - listIndent);
			cursor.setBlockFormat(blockFormat);
		}
	}

	document()->blockSignals(previousSignalState);
}

void FormattedEditor::insertTable(int rows, int cols)
{
	TableChange tableChg(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().position(), rows, cols);
	QTextTableFormat format;
	QVector<QTextLength> constraints;

	// Set spacing between borders and content.
	format.setCellPadding(4);

	// Set default width of table columns so that users can see what they are doing).
	// Works, but then it isn't variable.
	for (int i = 0; i < cols; i++)
		constraints << QTextLength(QTextLength::PercentageLength, 85 / cols);

	format.setColumnWidthConstraints(constraints);

	document()->blockSignals(true);
	textCursor().insertTable(rows, cols, format);
	document()->blockSignals(false);

	documentManager->sendChange(tableChg.toBytes());
}

void FormattedEditor::insertImage(QString fname)
{
	//load the image file
	QFile imgFile(fname);

	if (!imgFile.open(QIODevice::ReadOnly))
	{
		QMessageBox err(QMessageBox::Critical, "Error!", "Could not open file!");
		err.exec();
		return;
	}

	QByteArray imgData = imgFile.readAll();

	QImage img;

	if (!img.loadFromData(imgData))
	{
		QMessageBox err(QMessageBox::Critical, "Error!", "Could not load image!");
		err.exec();
		return;
	}

	//send change and update document
	ImageChange imgChg(revisionNum++, documentManager->getLocalUserId(), docId, textCursor().position(), img.width(), img.height(), imgData);

	document()->blockSignals(true);
	textCursor().insertImage(img, fname);
	document()->blockSignals(false);

	documentManager->sendChange(imgChg.toBytes());
}

void FormattedEditor::saveFile(QString filename)
{
	QByteArray myBytes;
	QFile out(filename);
	out.open(QIODevice::WriteOnly);
	this->saveFile(myBytes);
	out.write(myBytes);
	out.close();
}

void FormattedEditor::saveFile(QByteArray& myBytes)
{
    myBytes=toHtml().toLatin1();
}

QString FormattedEditor::saveSession(QString filename)
{
    QString line = "";

    //Call base class
    line = this->Editor::saveSession(filename);

    //Save formattedEditor specific variables
	//filename
    line += ":" + fileName + ":1";  //1 for formatted type editor

    return line;
}

void FormattedEditor::loadSession(QString filename, QStringList metadata)
{
    Editor::loadSession(filename, metadata);    //Call base class load

    //Set formatted editor specific data
    fileName = metadata.at(3).toLocal8Bit().constData();

}

void FormattedEditor::loadFile(QString filename)
{
    QByteArray myBytes;
    QFile file(filename);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
	return;

    myBytes = file.readAll();	//Read in data

    this->loadFile(myBytes);	//Set in the document

    file.close();
}

void FormattedEditor::loadFile(QByteArray myBytes)
{
    bool prev = document()->blockSignals(true);
    setHtml(myBytes);    //Add data back to the document
    document()->blockSignals(prev);
}

void FormattedEditor::setMeta(QStringList metadata)
{
    //Set other information
    fileName = metadata.at(3).toLocal8Bit().constData();

    this->Editor::setMeta(metadata);	//Set other metadata
}

QString FormattedEditor::getMeta()
{
    QString line="";

    line = this->Editor::getMeta();

    line += ":" + fileName + ":1\n";  //1 for formatted type editor

    return line;
}
